#pragma once
#include "index.hpp"
#include <algorithm>
#include <jsoncpp/json/json.h>


namespace ns_searcher
{
	struct InvertedElemPrint
	{
		uint64_t doc_id;
		int weight;
		std::vector<std::string> words;
		InvertedElemPrint()
		:doc_id(0),weight(0)
		{}
	};
    class Searcher
    {
    private:
        ns_index::Index* index;//查找用索引
    public:
        Searcher(){}
        ~Searcher(){}
    public:
        void InitSearcher(const std::string& input)
        {
            //1.获取或创建index对象
            index = ns_index::Index::GetInstance();
            //std::cout<<"获取index单例成功..."<<std::endl;
			LOG(NORMAL,"获取index单例成功...");
            //2. 根据index对象构建索引
            index->BuildIndex(input);
            //std::cout<<"建立正排和倒排序列成功..."<<std::endl;
			LOG(NORMAL,"获取index单例成功...");
        }
        //query: 搜索关键字
        //json_sting: 返回给浏览器的搜索结果
        void Search(const std::string& query,std::string* json_string)
        {
            //1. 分词：对query进行分词
            std::vector<std::string> words;
            ns_util::JiebaUtil::CutString(query,&words);
            //2. 触发：根据分词后的结果进行index查找
            //ns_index::InvertedList inverted_list_all;
			std::vector<InvertedElemPrint> inverted_list_all;
			std::unordered_map<uint64_t,InvertedElemPrint> tokens_map;//用于对相同id的倒排拉链去重

            for(std::string word : words)
            {
                boost::to_lower(word);
                ns_index::InvertedList* inverted_list = index->GetInvertedList(word);
                if(nullptr == inverted_list)
                    continue;
                //inverted_list_all.insert(inverted_list_all.end(),inverted_list->begin(),inverted_list->end());
				
				for(const auto& elem : *inverted_list)
				{
					auto& it = tokens_map[elem.doc_id];
					it.doc_id = elem.doc_id;
					it.weight += elem.weight;
					it.words.push_back(elem.word);
				}
            }
			for(auto& it : tokens_map)
			{
				inverted_list_all.push_back(std::move(it.second));
			}
            //3. 合并排序： 汇总查找结果，更具相关性weight进行降序排序
            std::sort(inverted_list_all.begin(),inverted_list_all.end(),\
            [](const InvertedElemPrint& e1,const InvertedElemPrint& e2)\
            {
                return e1.weight > e2.weight;
            });
            //4. 构建：根据查找结果，构建json串
            Json::Value root;
            for(auto& item : inverted_list_all)
            {
                ns_index::DocInfo* doc = index->GetForwardIndex(item.doc_id);
                if(nullptr == doc)
                    continue;
                Json::Value elem;
                elem["title"] = doc->title;
                elem["desc"] = GetDesc(doc->content,item.words[0]);
                elem["url"] = doc->url;
                elem["id"] = (int)item.doc_id;
                elem["weight"] = item.weight;

                root.append(elem);
            }
            Json::StyledWriter writer;
            *json_string = writer.write(root);
        }
		//获取摘要
		std::string GetDesc(const std::string& html_content,const std::string& word)
		{
			//简易实现：找到关键字前的50字节和后100字节，没有则找到文件头或尾
			const int prev_step = 50;
			const int next_step = 100;
			auto it = std::search(html_content.begin(),html_content.end(),word.begin(),word.end(),[](char x,char y){
					return (std::tolower(x) == std::tolower(y));
					});
			if(it == html_content.end())
				return "None1";
			int pos = std::distance(html_content.begin(),it);
			int start = 0;
			int end = html_content.size() - 1;
			if(pos > start + prev_step) start = pos - prev_step;
			if(pos < end - next_step) end = pos + next_step;

			if(start >= end) return "None2";
			std::string desc = html_content.substr(start,end - start+1);
			return desc;
		}
    };
}
